//
//  ToDoModel.swift
//
//  Created by 邱仙凯 on 2024/6/26
//  Copyright (c) . All rights reserved.
//

import Foundation
import ObjectMapper


// 不同项目表字段不同
protocol SerializationProtocol {
    func getSerializationkeys()
}







// 字段类型
enum TemplateType:String {
    case input,
         number,
         integer = "number1",
         number2,
         date,month,datetime,lov,arealov,editlov,
         localSelect = "select",
         baselovtree,companylovtree,
         dormlovtree,btnevent,btnevent_lov,
         btnevent_exec,radio,file,note,gangedlov,
         coordinate,slidingblock,map,tree,
         invoice,
         proCityDistrict  // 定制的省市县接口获取  回填采用 下拉选回填字段回填字段
         
}

// 返回的url截取出路径和原始参数数组   aaa/bbbb/cccc    [param=${z_org_id},param2=]
// 特殊关键字数组   （page   size   keyword   mobiletoken   mobileauthid）

// 返回  路径  正常数组  特殊关键字数组
struct PathHandler {
    var path = ""
    var comPa = [String]()
    var spePa = [String]() // 特殊参数数组   page   size   keyword
}

// 语法类型
enum GrammarType:String {
    case setSaveVerify,setModifyForbidden,setViewForbidden,setAddForbidden,setContinueAdd,setLimitMakerModify,
         getDateSelectType, // 养殖场定制的日期选择类型，会显示每日单据数
         setCompanyTreeParam,
         setRegularExp,
         setDetailUnique,setDependenceField,getCoordinate,setScanOutside,
         setBtnShow,// setBtnShow 示例 \n setBtnShow@{删除:${auditmark}==0&&${auditmarkxx}==2}
         //  主要用于列表按钮
         setRoundDown,
         setCheckDevice,
         setGesturePwd,// 设置手势密码保护
         setDetailTitle, // 设置细表小标题
         setDetailCombine,  // 细表通过该字段整合，合并细表
         setListGroup,  // 设置列表分组
         setMapCoordinate,// 设置地图类型的经纬度取值
         setWebForm,
         
         // 条件颜色  前面是条件 后面是颜色
         // setConditionalColor@{${z_live_hm_value}>99.5:e3e3e3};setConditionalColor@{${z_live_hm_value}>98&&${z_live_hm_value}<99.5:e3aae3}
         setConditionalColor,
         // 改变按钮名称, 只针对 submitButton 生效, 使用三目运算符. 语法: setFormButton@{a.c_status}=1?取消提交:提交修改
         setFormButton
}


func url2PathOriParam(_ url:String) -> PathHandler {
    let dealedUrl = url.removeAllSapce.removeLineFeed
    if dealedUrl.contains("?") {
        let path = dealedUrl.preChar(char: "?").unwrap
        let arr = dealedUrl.sufChar(char: "?").unwrap.components(separatedBy: "&")
        
        
        let arr1 = arr.filter{ !($0.contains("page") ||
                                 $0.contains("size") ||
                                 $0.contains("keyword") ||
                                 $0.contains("scanResult")) }
        
        let arr2 = arr.filter{ ($0.contains("page") ||
                                $0.contains("size") ||
                                $0.contains("keyword") ||
                                $0.contains("scanResult")) }
        
        
        
        return PathHandler(path: path, comPa: arr1, spePa: arr2)
    } else {
        return PathHandler(path: dealedUrl, comPa: [], spePa: [])
    }
    
}
// 先把语句按  分号 或逗号分割成数组
func getParammerArr(_ str:String) -> [String] {
    // 去空格  去换行
    let tempStr = str.removeAllSapce.removeLineFeed
    var resultArr = [String]()
    if tempStr.contains(";set") {
        resultArr = tempStr.components(separatedBy: ";").filter{ $0 != "" }
    } else if tempStr.contains(",set")  {
        resultArr = tempStr.components(separatedBy: ",").filter{ $0 != "" }
    } else  if tempStr.contains(";get") {
        resultArr = tempStr.components(separatedBy: ";").filter{ $0 != "" }
    } else if tempStr.contains(",get")  {
        resultArr = tempStr.components(separatedBy: ",").filter{ $0 != "" }
    } else {
        // 没有遇到就说明只有一组
        resultArr = [tempStr]
    }
    return resultArr.filter{ $0 != "" }
}
// 单个关键字语法解析
func getKeyPara(_ str:String) -> [String] {
    var tempStr = ""
    var tempArr = [String]()
    if str.contains("setClearDetails") { // 清空细表单独处理
        tempArr = ["setClearDetails"]
    } else if str.contains("@") {
        tempStr = str.removeAllSapce.removeLineFeed
        
        
        
        var result = "" // 累计字符
        var ignoreFlag = false // 忽略括号标识，打开说明下一个括号忽略
        var endFlag = true // 结束标识，里面的括号都套完了就结束
        tempStr.forEach { c in
            let s = String(c)
            if s == "@" {
                tempArr.append(result)
                result = ""
                ignoreFlag = true
            } else if s == "{" {
                if ignoreFlag {
                    ignoreFlag = false
                } else {
                    
                    result += s
                    endFlag = false // 开了个左括号，等右括号
                }
                
            } else if s == "}" {
                if endFlag {
                    tempArr.append(result)
                    result = ""
                } else {
                    result += s
                    endFlag = true // 等到了右括号，可以结束了
                }
            } else {
                result += s
            }
        }
        if result.count > 0 {
            tempArr.append(result)
        }
        
        
    } else if str.contains("$") {
        tempStr = str.removeAllSapce.removeLineFeed
        
        
        var result = "" // 累计字符
        var ignoreFlag = false // 忽略括号标识，打开说明下一个括号忽略
        var endFlag = true // 结束标识，里面的括号都套完了就结束
        tempStr.forEach { c in
            let s = String(c)
            if s == "$" {
                tempArr.append(result)
                result = ""
                ignoreFlag = true
            } else if s == "{" {
                if ignoreFlag {
                    ignoreFlag = false
                } else {
                    
                    result += s
                    endFlag = false // 开了个左括号，等右括号
                }
                
            } else if s == "}" {
                if endFlag {
                    tempArr.append(result)
                    result = ""
                } else {
                    result += s
                    endFlag = true // 等到了右括号，可以结束了
                }
            } else {
                result += s
            }
        }
        if result.count > 0 {
            tempArr.append(result)
        }
        
        
    }
    
    return tempArr.filter{ $0 != "" }
}
//  setClear${a.bbbb}${b.ccccc},setDisable${a.bbbb}

extension String {
    // 去掉中括号
    var removeBrackets:String {
        return self.replacingOccurrences(of: "{", with: "").replacingOccurrences(of: "}", with: "")
    }
    // 仅去掉最外层中括号，不会影响里面的中括号
    var removeOuterBrackets:String {
        
        
        var leftGet = false // 左边处理好了
        var result = "" // 累计字符
        var countFlag = 0
        self.forEach { c in
            let s = String(c)
            if s == "{" && leftGet == false {
                leftGet = true
            } else if s == "{" && leftGet == true {
                result += s
                countFlag += 1
            } else if s == "}" && countFlag != 0 {
                result += s
                countFlag -= 1
            } else if s == "}" && countFlag == 0 {
                
            } else {
                result += s
            }
        }
        
        return result
    }
    
    // 去掉$和@
    var removeDolendAt:String {
        return self.replacingOccurrences(of: "$", with: "").replacingOccurrences(of: "@", with: "")
    }
    
}
// 替换字段的值，返回 两种格式  字符串格式  和 数组格式
func getDolVal(_ str:String,main:[String:Any]? = nil,currDet:[String:Any]? = nil,rootTemp:MainTempModel) -> (String,[String]) {
    
    // 去空格  去换行 去$
    let tempStr = str.removeAllSapce.removeLineFeed.replacingOccurrences(of: "$", with: "")
    
    var result = ""
    var tempArr = [String]()
    tempStr.forEach { c in
        let s = String(c)
        if s == "{" {
            tempArr.append(result)
            result = "{"
        } else if s == "}" {
            result += s
            tempArr.append(result)
            result = ""
        } else {
            result += s
        }
    }
    if result.count > 0 {
        tempArr.append(result)
    }
    let endS = valueReplaceDic(tempArr.filter{ $0 != "" },main:main,currDet: currDet, rootTemp: rootTemp)
    return endS
}
// 把字段替换为值  返回 两种格式  字符串格式  和 数组格式
func valueReplaceDic(_ arr:[String],main:[String:Any]? = nil,currDet:[String:Any]? = nil,rootTemp:MainTempModel) -> (String,[String]) {
    var dfstr = ""
    var dfArr = [String]()
    
    for item in arr {
        if item.contains("{") {
            // 所有的细表取值先判断
            if containDDPa(condition: item, rootTemp: rootTemp) != "" {
                let vvv = item.removeBrackets.removeDolendAt.sufChar(char: ".").unwrap
                KSLog("细表取值·~~~~")
                KSLog(item)
                KSLog(vvv)
                if let dd = currDet {
                    // 取传进来的字段
                    let cv = any2Str(dd[vvv])
                    KSLog(cv)
                    dfstr += cv
                    dfArr.append(cv)
                }
            } else  if item.contains("a.") {
                let vvv = item.removeBrackets.removeDolendAt.replacingOccurrences(of: "a.", with: "")
                if let dd = main {
                    // 取传进来的字段
                    let cv = any2Str(dd[vvv])
                    dfstr += cv
                    dfArr.append(cv)
                }
            }  else if item.contains("p.") {
                let vvv = item.removeBrackets.removeDolendAt.replacingOccurrences(of: "p.", with: "")
                // 取登录信息
                let cv = any2Str(getValueByKey(obj: USERINFO, key: vvv.camelName))
                dfstr += cv
                dfArr.append(cv)
            } else {
                
                if let dd = main {
                    let vvv = item.removeBrackets.removeDolendAt.replacingOccurrences(of: "a.", with: "")
                    // 取传进来的字段
                    let cv = any2Str(dd[vvv])
                    dfstr += cv
                    dfArr.append(cv)
                } else {
                    let vvv = item.removeBrackets.removeDolendAt.replacingOccurrences(of: "p.", with: "")
                    // 取登录信息
                    let cv = any2Str(getValueByKey(obj: USERINFO, key: vvv.camelName))
                    dfstr += cv
                    dfArr.append(cv)
                }
            }
            
        } else {
            dfArr.append(item)
            dfstr += item
        }
    }
    return (dfstr,dfArr)
}
// 表达式包含了细表元素 返回匹配到的 细表前缀  没匹配则返回空字符串
func containDDPa(condition:String,rootTemp:MainTempModel) -> String {
    var detailPre = ""

    let paAr  = rootTemp.multiDetailsParams
   
    for item in paAr {
        if condition.contains("\(item).") {
            detailPre = item
        }
    }
    if condition.contains("b.") {
        detailPre = "b"
    }
    
    return  detailPre

}
func dateId2Value(_ id:String) -> String {
    var suf = ""
    switch id {
    case "1":
        suf = Date.today
    case "2":
        suf = Date.firstDateOfMonth
    case "3":
        suf = Date.todayPres(30)
    case "4":
        suf = Date.todayPres(60)
    case "5":
        suf = Date.todayPres(90)
    case "6":
        suf = Date.todayAfter(7)
    case "7":
        suf = Date.todayPres(365)
    default:
        break
    }
    return suf
}
// [param=${z_org_id},param2=]  并把参数赋值  主表取值  和细表取值
func url2PathDic(mainDic:[String:Any]? = nil,currDetaiDic:[String:Any]? = nil,arr:[String]) -> [String:String] {
    
    var dic = [String:String]()
    for i in 0..<arr.count {
        
        let preOri = arr[i].preChar(char: "=").unwrap
        var suf = arr[i].sufChar(char: "=").unwrap
        
        var realKey = preOri
        if realKey.contains(".") {
            realKey = realKey.sufChar(char: ".").unwrap
        }
        if suf == "" { // 等号后面没有值，会把前面当 参数去主表或细表取值
            
            if preOri.contains(".") { // 包含. 说明指定了主表或细表
                let preFrom =  preOri.preChar(char: ".").unwrap
                let preSuf =  preOri.sufChar(char: ".").unwrap
                if preFrom == "p" {// 个人信息取值
                    let cv = any2Str(getValueByKey(obj: USERINFO, key: preSuf.camelName))
                    suf = cv
                } else if preFrom == "b" {
                    if let dd = currDetaiDic {
                        suf = any2Str(dd[preSuf])
                    }
                } else {
                    // a. 或者没写都是  取主表
                    if let md = mainDic {
                        suf = any2Str(md[preSuf])
                    }
                }
                
                dic.updateValue(suf, forKey: realKey)
            } else {
                if let md = mainDic {
                    dic.updateValue(any2Str(md[preOri]), forKey: realKey)
                }
            }
        } else if suf.contains("$") {
            // 等号后面有值，就按指定的参数去主表细表取值
            let tempParam = suf.replacingOccurrences(of: "$", with: "").replacingOccurrences(of: "{", with: "").replacingOccurrences(of: "}", with: "")
            
            
            if tempParam.contains(".") { // 包含. 说明指定了主表或细表
                
                
                
                let preTp =  tempParam.preChar(char: ".").unwrap
                let sufTp =  tempParam.sufChar(char: ".").unwrap
                if preTp == "p" {
                    // 个人信息取值
                    let cv = any2Str(getValueByKey(obj: USERINFO, key: sufTp.camelName))
                    suf = cv
                } else if preTp == "b" {
                    // 单一细表取值
                    if let dd = currDetaiDic {
                        suf = any2Str(dd[sufTp])
                    }
                } else if preTp == "i" {
                    // i是输入， 把值留着
                    
                } else if preTp == "a" {
                    // 主表取值
                    if let md = mainDic {
                        suf = any2Str(md[sufTp])
                    }
                } else {
                    if preTp != "" {
                        // 单一细表取值
                        if let dd = currDetaiDic {
                            suf = any2Str(dd[sufTp])
                        }
                    } else {
                        KSToast("取值请规范填写 a.  b. 等")
                    }
                    
                    
                }
                dic.updateValue(suf, forKey: realKey)
            } else {
                if let md = mainDic {
                    dic.updateValue(any2Str(md[tempParam]), forKey: realKey)
                }
            }
        } else {
            dic.updateValue(suf, forKey: realKey)
        }
        
    }
    return dic
    
    
    
}
// 主表数据   当前细表数据   当前模板
func commonTree(type:OrgSelectType,mainDic:[String:Any]? = nil,currDetaiDic:[String:Any]? = nil,onexx:TemplateModel,backClo:(([NormalTreeNode])->())?) {
    let pathDic = url2PathDic(mainDic: mainDic,currDetaiDic: currDetaiDic,arr: onexx.pathHandler.comPa)
    var showParam = ""
    for item in onexx.lovShowArr {
        let pre = item.preChar(char: ":").unwrap
        let suf = item.sufChar(char: ":").unwrap
        showParam = pre
    }
    NormalTree.initWithNav(showParam:showParam,api:API.temp(.path(path: onexx.pathHandler.path, paramDic: pathDic)),type: type,backClosure: { nodes in
        if let clo = backClo {
            clo(nodes)
        }
        
     
        
     }) { vc in
        let topViewController = RouterUtils.currentTopViewController()
        topViewController!.present_FullScreen(to: vc)
    }
    

}
// 基地树   id  name   公司树  id   name
class NormalTreeNode: Mappable {
    
    var dic = [String:Any]()
    var pId:String?
    var id:String?
    
    var children:[NormalTreeNode]?
    var level:Int?
    var color:UIColor!
    var open = true // 树节点的展开与关闭
    var selected = false // 选中标识
    var matched = true // 搜索的匹配标识，不匹配不显示
    var type:OrgSelectType!
 
   
    required init?(map: Map) {
         
    }
    // Mappable
    func mapping(map: Map) {
        pId <- (map["pId"],StringTransform())
         id <- (map["id"],StringTransform())
        children <- map["children"]
      
    }
}
struct AuditParamCombine {
    var info = TodoResult(JSON:["":""])!
    var model = ToDoModel(JSON:["":""])!
    var appr = AuditProcessAppear()
    var chooseUser = [ChooseUsers]()
    // 指定填单指定到了发起人，需要把大部分字段放开给填
 }

class DormTreeNode: Mappable {
   
   var z_org_nm: String?
   var z_item_nm:String?
   var z_production_line_id: String?
   var z_production_line_nm:String?
    var id_key:String?
   var z_last_mark:String?
   var lev_cd:Int?
   var children:[DormTreeNode]?
   var open = true // 树节点的展开与关闭
   var matched = true // 搜索的匹配标识，不匹配不显示
   var z_use_mark:Int?
   required init?(map: Map) {
       
   }
   // Mappable
   func mapping(map: Map) {
       z_last_mark <- (map["z_last_mark"],StringTransform())
       z_org_nm <- map["z_org_nm"]
       z_production_line_id <- (map["z_production_line_id"],StringTransform())
       z_production_line_nm <- map["z_production_line_nm"]
       id_key <- (map["id_key"],StringTransform())
       lev_cd <- map["lev_cd"]
       z_item_nm <- map["z_item_nm"]
       children <- map["children"]
       z_use_mark <- map["z_use_mark"]
   }
}
enum OrgSelectType {
   case single,multi
}
